// 第三方库动态导入管理器

export interface LibraryConfig {
  name: string;
  importFn: () => Promise<any>;
  preload?: boolean;
  priority?: 'high' | 'normal' | 'low';
  essential?: boolean; // 是否为核心库
  fallback?: any; // 降级方案
}

// 库加载状态
interface LibraryStatus {
  isLoading: boolean;
  isLoaded: boolean;
  library?: any;
  error?: Error;
  loadTime?: number;
}

/**
 * 动态库导入管理器
 */
export class DynamicLibraryManager {
  private libraries = new Map<string, LibraryStatus>();
  private loadPromises = new Map<string, Promise<any>>();

  /**
   * 注册库配置
   */
  register(config: LibraryConfig): void {
    if (!this.libraries.has(config.name)) {
      this.libraries.set(config.name, {
        isLoading: false,
        isLoaded: false
      });
    }

    // 预加载核心库
    if (config.preload || config.essential) {
      this.preloadLibrary(config);
    }
  }

  /**
   * 动态导入库
   */
  async import<T = any>(
    name: string, 
    importFn: () => Promise<T>,
    fallback?: T
  ): Promise<T | null> {
    // 检查是否已加载
    const status = this.libraries.get(name);
    if (status?.isLoaded && status.library) {
      return status.library;
    }

    // 检查是否正在加载
    if (this.loadPromises.has(name)) {
      try {
        return await this.loadPromises.get(name)!;
      } catch (error) {
        console.error(`[动态导入] 等待库 ${name} 加载失败:`, error);
        return fallback || null;
      }
    }

    // 开始加载
    const loadPromise = this.loadLibrary(name, importFn, fallback);
    this.loadPromises.set(name, loadPromise);

    try {
      const library = await loadPromise;
      this.loadPromises.delete(name);
      return library;
    } catch (error) {
      this.loadPromises.delete(name);
      throw error;
    }
  }

  /**
   * 加载库的具体实现
   */
  private async loadLibrary<T>(
    name: string,
    importFn: () => Promise<T>,
    fallback?: T
  ): Promise<T | null> {
    const status = this.libraries.get(name) || {
      isLoading: false,
      isLoaded: false
    };

    try {
      console.log(`[动态导入] 开始加载库: ${name}`);
      const startTime = performance.now();

      status.isLoading = true;
      this.libraries.set(name, status);

      const library = await importFn();
      const loadTime = performance.now() - startTime;

      status.isLoading = false;
      status.isLoaded = true;
      status.library = library;
      status.loadTime = loadTime;
      status.error = undefined;

      this.libraries.set(name, status);

      console.log(`[动态导入] 库 ${name} 加载成功，耗时: ${loadTime.toFixed(2)}ms`);
      return library;

    } catch (error) {
      console.error(`[动态导入] 库 ${name} 加载失败:`, error);

      status.isLoading = false;
      status.isLoaded = false;
      status.error = error as Error;
      this.libraries.set(name, status);

      // 返回降级方案
      if (fallback) {
        console.log(`[动态导入] 使用库 ${name} 的降级方案`);
        return fallback;
      }

      return null;
    }
  }

  /**
   * 预加载库
   */
  private async preloadLibrary(config: LibraryConfig): Promise<void> {
    try {
      await this.import(config.name, config.importFn, config.fallback);
    } catch (error) {
      console.error(`[动态导入] 预加载库 ${config.name} 失败:`, error);
    }
  }

  /**
   * 检查库是否已加载
   */
  isLibraryLoaded(name: string): boolean {
    return this.libraries.get(name)?.isLoaded || false;
  }

  /**
   * 获取库状态
   */
  getLibraryStatus(name: string): LibraryStatus | undefined {
    return this.libraries.get(name);
  }

  /**
   * 获取所有库的状态
   */
  getAllLibrariesStatus(): Map<string, LibraryStatus> {
    return new Map(this.libraries);
  }

  /**
   * 卸载库
   */
  unloadLibrary(name: string): void {
    const status = this.libraries.get(name);
    if (status) {
      status.isLoaded = false;
      status.library = undefined;
      this.libraries.set(name, status);
    }
    console.log(`[动态导入] 库 ${name} 已卸载`);
  }

  /**
   * 清理所有库
   */
  clearAll(): void {
    this.libraries.clear();
    this.loadPromises.clear();
    console.log('[动态导入] 所有库已清理');
  }
}

// 全局动态库管理器
export const dynamicLibraryManager = new DynamicLibraryManager();

// 常用库配置
export const commonLibrariesConfig: LibraryConfig[] = [
  {
    name: 'monaco-editor',
    importFn: () => import('monaco-editor'),
    preload: false,
    priority: 'high',
    essential: false
  },
  {
    name: 'jszip',
    importFn: () => import('jszip'),
    preload: false,
    priority: 'normal',
    essential: false
  },
  {
    name: 'file-saver',
    importFn: () => import('file-saver'),
    preload: false,
    priority: 'normal',
    essential: false
  },
  {
    name: 'react-dnd',
    importFn: () => import('react-dnd'),
    preload: false,
    priority: 'normal',
    essential: false
  },
  {
    name: 'react-dnd-html5-backend',
    importFn: () => import('react-dnd-html5-backend'),
    preload: false,
    priority: 'normal',
    essential: false
  }
];

/**
 * 初始化动态库管理器
 */
export function initializeDynamicLibraries(): void {
  console.log('[动态导入] 初始化动态库管理器');
  
  // 注册常用库
  commonLibrariesConfig.forEach(config => {
    dynamicLibraryManager.register(config);
  });

  console.log('[动态导入] 动态库管理器初始化完成');
}

// 便捷的动态导入函数
export const dynamicImport = {
  // Monaco Editor
  monacoEditor: () => dynamicLibraryManager.import(
    'monaco-editor',
    () => import('monaco-editor')
  ),

  // JSZip
  jszip: () => dynamicLibraryManager.import(
    'jszip',
    () => import('jszip')
  ),

  // File Saver
  fileSaver: () => dynamicLibraryManager.import(
    'file-saver',
    () => import('file-saver')
  ),

  // React DnD
  reactDnD: () => dynamicLibraryManager.import(
    'react-dnd',
    () => import('react-dnd')
  ),

  // React DnD HTML5 Backend
  reactDnDHTML5Backend: () => dynamicLibraryManager.import(
    'react-dnd-html5-backend',
    () => import('react-dnd-html5-backend')
  )
};

// React Hook for dynamic import
export function useDynamicImport<T = any>(
  name: string,
  importFn: () => Promise<T>,
  fallback?: T
): {
  library: T | null;
  isLoading: boolean;
  error: Error | null;
  reload: () => Promise<void>;
} {
  const [state, setState] = React.useState<{
    library: T | null;
    isLoading: boolean;
    error: Error | null;
  }>({
    library: null,
    isLoading: false,
    error: null
  });

  const load = React.useCallback(async () => {
    setState(prev => ({ ...prev, isLoading: true, error: null }));
    
    try {
      const library = await dynamicLibraryManager.import(name, importFn, fallback);
      setState({
        library,
        isLoading: false,
        error: null
      });
    } catch (error) {
      setState({
        library: fallback || null,
        isLoading: false,
        error: error as Error
      });
    }
  }, [name, importFn, fallback]);

  React.useEffect(() => {
    load();
  }, [load]);

  const reload = React.useCallback(async () => {
    await load();
  }, [load]);

  return {
    ...state,
    reload
  };
}

import React from 'react';